

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Loging;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.Sms;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using Essensoft.Paylink.Alipay.Domain;
using Essensoft.Paylink.WeChatPay.V3.Domain;
using Flurl.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using Tea;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.WxaApiUserLogSearchResponse.Types.Data.Types.RealtimeLog.Types;


namespace CoreCms.Net.Services
{
    /// <summary>
    /// 短信发送日志 接口实现
    /// </summary>
    public class CoreCmsSmsServices : BaseServices<CoreCmsSms>, ICoreCmsSmsServices
    {
        private readonly ICoreCmsSmsRepository _dal;
        private readonly ICoreCmsSettingServices _settingServices;
        private readonly IUnitOfWork _unitOfWork;

        private readonly IHttpContextAccessor _httpContextAccessor;

        public CoreCmsSmsServices(IUnitOfWork unitOfWork
            , ICoreCmsSmsRepository dal
            , IHttpContextAccessor httpContextAccessor, ICoreCmsSettingServices settingServices)
        {
            this._dal = dal;
            base.BaseDal = dal;
            _unitOfWork = unitOfWork;

            _httpContextAccessor = httpContextAccessor;
            _settingServices = settingServices;
        }




        #region 发送短信（验证码）

        /// <summary>
        /// 发送短信（验证码）
        /// </summary>
        /// <param name="type"></param>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public async Task<WebApiCallBack> DoSendSms(string type, string mobile)
        {
            var jm = new WebApiCallBack();
            var smsOptions = await _settingServices.GetSmsOptions();
            if (smsOptions.Enabled == false)
            {
                jm.msg = "短信功能未开启";
                return jm;
            }

            Random rd = new Random();
            int codeNumber = rd.Next(100000, 999999);


            var dt = DateTime.Now;

            //获取当前ip今日的发送记录
            var ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString() : "127.0.0.1";
            if (string.IsNullOrEmpty(ip))
            {
                jm.msg = "短信发送IP获取失败";
                return jm;
            }
            var black = smsOptions.SmsIpSendBlackList.Split('|').ToList();
            if (black.Count > 0 && black.Contains(ip))
            {
                jm.msg = "此IP被禁止短信业务";
                return jm;
            }
            var white = smsOptions.SmsIpSendWhiteList.Split('|').ToList();
            if (white.Count <= 0 || !white.Contains(ip))
            {
                var startDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0, DateTimeKind.Utc);
                var endDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59, DateTimeKind.Utc);

                var sendCount = await _dal.GetCountAsync(p => p.ip.Equals(ip) && p.createTime > startDateTime && p.createTime < endDateTime);
                if (smsOptions.SmsIpSendNumber > 0 && sendCount > smsOptions.SmsIpSendNumber)
                {
                    jm.msg = "此IP被已超过每日短信发送限额。";
                    return jm;
                }
            }

            //获取是否存在
            var endDt = dt.AddMinutes(10);

            var oldLog = await _dal.QueryByClauseAsync(p => p.code == type && p.mobile == mobile && p.createTime > dt && p.createTime < endDt, p => p.id, OrderByType.Desc);
            if (oldLog == null)
            {
                oldLog = new CoreCmsSms();
                oldLog.code = type;
                oldLog.createTime = dt;
                oldLog.mobile = mobile;
                oldLog.ip = ip;
                oldLog.isUsed = false;
                var obj = new
                {
                    code = codeNumber
                };
                if (type == "login")
                {
                    if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.KingTto)
                    {
                        oldLog.contentBody = "您本次登陆的验证码是：" + codeNumber + "，请不要将验证码泄露给他人！";
                        oldLog.parameters = JsonConvert.SerializeObject(obj);
                    }
                    else if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.AliYun)
                    {
                        oldLog.contentBody = smsOptions.SmsAliYunTplForLogin;
                        oldLog.parameters = JsonConvert.SerializeObject(new
                        {
                            code = codeNumber.ToString()
                        });
                    }
                }
                else
                {
                    if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.KingTto)
                    {
                        oldLog.contentBody = "您验证码是：" + codeNumber + "，请不要将验证码泄露给他人！";
                        oldLog.parameters = JsonConvert.SerializeObject(obj);
                    }
                    else if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.AliYun)
                    {
                        oldLog.contentBody = smsOptions.SmsAliYunTplForVeri;
                        oldLog.parameters = JsonConvert.SerializeObject(new
                        {
                            code = codeNumber.ToString()
                        });
                    }
                }
                await _dal.InsertAsync(oldLog);
            }

            if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.KingTto)
            {
                var result = await SendSms(oldLog.mobile, oldLog.contentBody, smsOptions);

                jm.status = result.IsSuccess;
                jm.msg = result.IsSuccess ? "发送成功" : result.Message;
                jm.otherData = result;

            }
            else if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.AliYun)
            {

                if (type == "login" && string.IsNullOrEmpty(smsOptions.SmsAliYunTplForLogin))
                {
                    jm.msg = "阿里云登录短信模板未设置";
                    return jm;
                }

                if (type != "login" && string.IsNullOrEmpty(smsOptions.SmsAliYunTplForVeri))
                {
                    jm.msg = "阿里云验证码短信模板未设置";
                    return jm;
                }

                var config = new AlibabaCloud.OpenApiClient.Models.Config
                {
                    // 必填，您的 AccessKey ID
                    AccessKeyId = smsOptions.Account,
                    // 必填，您的 AccessKey Secret
                    AccessKeySecret = smsOptions.Password,
                    //Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
                    Endpoint = smsOptions.ApiUrl,

                };
                var client = new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);

                var sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest();
                var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();

                try
                {
                    sendSmsRequest.SignName = smsOptions.Signature;
                    sendSmsRequest.PhoneNumbers = mobile;
                    sendSmsRequest.TemplateCode =
                        type == "login" ? smsOptions.SmsAliYunTplForLogin : smsOptions.SmsAliYunTplForVeri;
                    sendSmsRequest.TemplateParam = JsonConvert.SerializeObject(new
                    {
                        code = codeNumber.ToString()
                    });
                    sendSmsRequest.OutId = Guid.NewGuid().ToString();

                    var result = await client.SendSmsWithOptionsAsync(sendSmsRequest, runtime);

                    if (result.Body.Code == "OK")
                    {
                        jm.status = true;
                        jm.msg = "发送成功";
                    }
                    else
                    {
                        jm.status = false;
                        jm.msg = "发送失败:" + result.Body.Message;
                    }

                    jm.otherData = result;

                }
                catch (TeaException error)
                {
                    jm.status = false;
                    jm.msg = "发送失败:" + error.Message;
                }
                catch (Exception _error)
                {
                    var error = new TeaException(new Dictionary<string, object>
                    {
                        { "message", _error.Message }
                    });

                    jm.status = false;
                    jm.msg = "发送失败:" + _error.Message;
                    jm.otherData = error.Data["Recommend"];
                }
            }
            return jm;
        }
        #endregion

        #region 校验短信验证码
        /// <summary>
        /// 校验短信验证码
        /// </summary>
        /// <param name="phone"></param>
        /// <param name="verCode"></param>
        /// <param name="code"></param>
        /// <returns></returns>

        public async Task<bool> Check(string phone, string verCode, string code)
        {
            var smsInfo = await _dal.QueryByClauseAsync(p =>
                p.mobile == phone && p.code == code && p.createTime < DateTime.Now && p.isUsed == false, p => p.createTime, OrderByType.Desc);
            if (smsInfo != null)
            {
                var parameters = JObject.Parse(smsInfo.parameters);
                if (parameters.ContainsKey("code"))
                {
                    var dataCode = parameters["code"]?.ToString();
                    if (dataCode != verCode) return false;
                    smsInfo.isUsed = true;
                    await _dal.UpdateAsync(smsInfo);
                    return true;
                }
                return false;
            }
            return false;
        }
        #endregion

        #region 接口通道发送短信

        /// <summary>
        /// 接口通道发送短信
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="contentBody"></param>
        /// <param name="smsOptions">配置文件</param>
        public async Task<SMSReturnData> SendSms(string mobile, string contentBody, SmsOptions smsOptions)
        {
            if (smsOptions.Enabled)
            {
                var result = await smsOptions.ApiUrl.PostUrlEncodedAsync(new
                {
                    action = "send",
                    userid = smsOptions.UserId,
                    account = smsOptions.Account,
                    password = smsOptions.Password,
                    mobile,
                    content = "【" + smsOptions.Signature + "】" + contentBody,
                    rt = "json"
                }).ReceiveJson<SMSReturnData>();
                result.IsSuccess = result.ReturnStatus.ToLowerInvariant() == "success";
                return result;
            }
            else
            {
                var result = new SMSReturnData()
                {
                    ReturnStatus = "faild",
                    Message = "短信功能未开启",
                    RemainPoint = 0,
                    TaskID = 0,
                    SuccessCounts = 0
                };
                return result;
            }
        }
        #endregion

        #region 发送短信统一方法
        /// <summary>
        /// 发送短信统一方法
        /// </summary>
        /// <param name="mobile">接受者手机号码</param>
        /// <param name="code">模板编码</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public async Task<WebApiCallBack> Send(string mobile, string code, JObject parameters)
        {
            var jm = new WebApiCallBack();
            var smsOptions = await _settingServices.GetSmsOptions();
            if (smsOptions.Enabled == false)
            {
                jm.msg = "短信功能未开启";
                return jm;
            }
            var dt = DateTime.Now;

            //获取当前ip今日的发送记录
            var ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString() : "127.0.0.1";
            if (string.IsNullOrEmpty(ip))
            {
                jm.msg = "短信发送IP获取失败";
                return jm;
            }
            var black = smsOptions.SmsIpSendBlackList.Split('|').ToList();
            if (black.Count > 0 && black.Contains(ip))
            {
                jm.msg = "此IP被禁止短信业务";
                return jm;
            }
            var white = smsOptions.SmsIpSendWhiteList.Split('|').ToList();
            if (white.Count <= 0 || !white.Contains(ip))
            {
                var startDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0,
                    DateTimeKind.Utc);
                var endDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 59, 59,
                    DateTimeKind.Utc);

                var sendCount = await _dal.GetCountAsync(p => p.ip.Equals(ip) && p.createTime > startDateTime && p.createTime < endDateTime);
                if (smsOptions.SmsIpSendNumber > 0 && sendCount > smsOptions.SmsIpSendNumber)
                {
                    jm.msg = "此IP被已超过每日短信发送限额。";
                    return jm;
                }
            }

            if (string.IsNullOrEmpty(mobile))
            {
                jm.msg = GlobalErrorCodeVars.Code11051;
                return jm;
            }
            var isUsed = false;
            string codeNumberStr = string.Empty;
            if (code == GlobalEnumVars.SmsMessageTypes.Reg.ToString() || code == GlobalEnumVars.SmsMessageTypes.Login.ToString() || code == GlobalEnumVars.SmsMessageTypes.Veri.ToString())
            {
                var newCreateTime = DateTime.Now.AddSeconds(-60);
                var smsInfo = await _dal.QueryByClauseAsync(p => p.mobile == mobile && p.code == code && p.createTime < newCreateTime && p.isUsed == false);
                if (smsInfo != null)
                {
                    var ts = dt - smsInfo.createTime;
                    if (ts.Seconds < 60)
                    {
                        jm.msg = "两次发送时间间隔小于60秒";
                        return jm;
                    }
                    parameters = JObject.Parse(smsInfo.parameters);
                    if (parameters.TryGetValue("code", out var parameter))
                    {
                        codeNumberStr = parameter?.ToString();
                    }
                }
                else
                {
                    Random rd = new Random();
                    int codeNumber = rd.Next(100000, 999999);
                    if (parameters.ContainsKey("code"))
                    {
                        parameters.Remove("code");
                    }
                    parameters.Add("code", codeNumber);
                    codeNumberStr = codeNumber.ToString();
                }
                isUsed = false;
            }
            else
            {
                isUsed = true;
            }

            var str = string.Empty;
            var allConfigs = await _settingServices.GetConfigDictionaries();

            if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.KingTto)
            {

                if (code == GlobalEnumVars.SmsMessageTypes.Reg.ToString())
                {
                    // 账户注册
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForReg);
                    if (!string.IsNullOrEmpty(msg))
                    {
                        str = msg.Replace("{code}", codeNumberStr);
                    }
                }
                else if (code == GlobalEnumVars.SmsMessageTypes.Login.ToString())
                {
                    // 账户登录
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForLogin);
                    if (!string.IsNullOrEmpty(msg))
                    {
                        str = msg.Replace("{code}", codeNumberStr);
                    }
                }
                else if (code == GlobalEnumVars.SmsMessageTypes.Veri.ToString())
                {
                    // 验证验证码
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForVeri);
                    if (!string.IsNullOrEmpty(msg))
                    {
                        str = msg.Replace("{code}", codeNumberStr);
                    }
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.CreateOrder.ToString())
                {
                    // 订单创建
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForCreateOrder);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.OrderPayed.ToString())
                {
                    // 订单支付通知买家
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForOrderPayed);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.RemindOrderPay.ToString())
                {
                    // 未支付催单
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForRemindOrderPay);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.DeliveryNotice.ToString())
                {
                    // 订单发货
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForDeliveryNotice);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.AfterSalesPass.ToString())
                {
                    // 售后审核通过
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForAfterSalesPass);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.RefundSuccess.ToString())
                {
                    // 退款已处理
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForRefundSuccess);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.SellerOrderNotice.ToString())
                {
                    // 订单支付通知卖家
                    var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForSellerOrderNotice);
                    str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.Common.ToString())
                {
                    //通用类型
                    var tpl = string.Empty;
                    if (parameters.ContainsKey("tpl"))
                    {
                        tpl = parameters["tpl"]?.ToString();
                    }
                    str = tpl;
                    if (string.IsNullOrEmpty(str))
                    {
                        var msg = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.SmsTplForCommon);
                        str = !string.IsNullOrEmpty(msg) ? msg : string.Empty;
                    }
                }

                if (string.IsNullOrEmpty(str))
                {
                    jm.msg = GlobalErrorCodeVars.Code10009;
                    return jm;
                }

                var oldLog = new CoreCmsSms();
                oldLog.mobile = mobile;
                oldLog.code = code;
                oldLog.parameters = JsonConvert.SerializeObject(parameters);
                oldLog.contentBody = str;
                oldLog.createTime = dt;
                oldLog.ip = ip;
                oldLog.isUsed = isUsed;

                await _dal.InsertAsync(oldLog);

                var result = await SendSms(oldLog.mobile, oldLog.contentBody, smsOptions);

                jm.status = result.IsSuccess;
                jm.msg = result.IsSuccess ? "发送成功" : result.Message;

                return jm;
            }
            else if (smsOptions.SmsType == (int)GlobalEnumVars.SmsType.AliYun)
            {
                var templateCode = string.Empty;
                object templateParam = null;
                if (code == GlobalEnumVars.SmsMessageTypes.Reg.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForReg;
                    templateParam = new
                    {
                        code = codeNumberStr
                    };
                }
                else if (code == GlobalEnumVars.SmsMessageTypes.Login.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForLogin;
                    templateParam = new
                    {
                        code = codeNumberStr
                    };
                }
                else if (code == GlobalEnumVars.SmsMessageTypes.Veri.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForVeri;
                    templateParam = new
                    {
                        code = codeNumberStr
                    };
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.CreateOrder.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForCreateOrder;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.OrderPayed.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForOrderPayed;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.RemindOrderPay.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForRemindOrderPay;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.DeliveryNotice.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForDeliveryNotice;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.AfterSalesPass.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForAfterSalesPass;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.RefundSuccess.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForRefundSuccess;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.SellerOrderNotice.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForSellerOrderNotice;
                }
                else if (code == GlobalEnumVars.PlatformMessageTypes.Common.ToString())
                {
                    templateCode = smsOptions.SmsAliYunTplForCommon;
                }

                if (string.IsNullOrEmpty(templateCode))
                {
                    jm.msg = GlobalErrorCodeVars.Code10009;
                    return jm;
                }

                var config = new AlibabaCloud.OpenApiClient.Models.Config
                {
                    // 必填，您的 AccessKey ID
                    AccessKeyId = smsOptions.Account,
                    // 必填，您的 AccessKey Secret
                    AccessKeySecret = smsOptions.Password,
                    //Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
                    Endpoint = smsOptions.ApiUrl,

                };
                var client = new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);

                var sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest();
                var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();

                try
                {
                    sendSmsRequest.SignName = smsOptions.Signature;
                    sendSmsRequest.PhoneNumbers = mobile;
                    sendSmsRequest.TemplateCode = templateCode;
                    sendSmsRequest.TemplateParam = JsonConvert.SerializeObject(templateParam);
                    sendSmsRequest.OutId = Guid.NewGuid().ToString();

                    var result = await client.SendSmsWithOptionsAsync(sendSmsRequest, runtime);

                    if (result.Body.Code == "OK")
                    {
                        var smsInfo = new CoreCmsSms();
                        smsInfo.mobile = mobile;
                        smsInfo.parameters = JsonConvert.SerializeObject(result);
                        smsInfo.code = code;
                        smsInfo.contentBody = templateCode;
                        smsInfo.createTime = DateTime.Now;
                        smsInfo.ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString() : "127.0.0.1";
                        smsInfo.isUsed = isUsed;

                        await _dal.InsertAsync(smsInfo);

                        jm.status = true;
                        jm.msg = "发送成功";
                    }
                    else
                    {
                        jm.status = false;
                        jm.msg = "发送失败:" + result.Body.Message;
                    }
                }
                catch (TeaException error)
                {
                    jm.status = false;
                    jm.msg = "发送失败:" + error.Message;
                }
                catch (Exception _error)
                {
                    var error = new TeaException(new Dictionary<string, object>
                    {
                        { "message", _error.Message }
                    });

                    jm.status = false;
                    jm.msg = "发送失败:" + _error.Message;
                    jm.otherData = error.Data["Recommend"];
                }
                return jm;

            }
            else
            {
                jm.status = false;
                jm.msg = "未获取到发送方式";
                return jm;
            }
        }
        #endregion
    }
}
